package com.gzstv.dlnasdk.upnp;

import com.gzstv.dlnasdk.util.HttpUtil;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import static java.net.HttpURLConnection.HTTP_OK;

public class ControlPoint {

    private static final String AV_TRANSPORT_SERVICE_ID = "urn:upnp-org:serviceId:AVTransport";
    private static final String AV_TRANSPORT_SERVICE_TYPE = "urn:schemas-upnp-org:service:AVTransport:1";
    private static final String RENDERING_CONTROL_SERVICE_TYPE = "urn:schemas-upnp-org:service:RenderingControl:1";

    private static Service getService(Device device) throws IOException {
        Service service = device.getService(AV_TRANSPORT_SERVICE_ID);
        if (service == null) {
            service = device.getService(AV_TRANSPORT_SERVICE_TYPE);
        }
        if (service == null) {
            throw new IOException("AVTransport service not found on device: " + device.getFriendlyName());
        }
        return service;
    }

    public static void setAVTransportURI(Device device, String uri, String metaData) throws IOException {
        Service service = getService(device);
        URL controlUrl = service.getControlURL();

        // Escape XML special characters in metaData
        String escapedMetaData = metaData.replace("&", "&amp;")
                                       .replace("<", "&lt;")
                                       .replace(">", "&gt;")
                                       .replace("\"", "&quot;")
                                       .replace("'", "&apos;");

        String soapAction = service.getServiceType() + "#SetAVTransportURI";
        String body = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                + "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
                + "<s:Body>"
                + "<u:SetAVTransportURI xmlns:u=\"" + service.getServiceType() + "\">"
                + "<InstanceID>0</InstanceID>"
                + "<CurrentURI>" + uri + "</CurrentURI>"
                + "<CurrentURIMetaData>" + escapedMetaData + "</CurrentURIMetaData>"
                + "</u:SetAVTransportURI>"
                + "</s:Body>"
                + "</s:Envelope>";

        sendPostRequest(controlUrl, soapAction, body);
    }

    public static void play(Device device) throws IOException {
        Service service = getService(device);
        URL controlUrl = service.getControlURL();

        String soapAction = service.getServiceType() + "#Play";
        String body = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                + "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
                + "<s:Body>"
                + "<u:Play xmlns:u=\"" + service.getServiceType() + "\">"
                + "<InstanceID>0</InstanceID>"
                + "<Speed>1</Speed>"
                + "</u:Play>"
                + "</s:Body>"
                + "</s:Envelope>";

        sendPostRequest(controlUrl, soapAction, body);
    }

    public static void pause(Device device) throws IOException {
        Service service = getService(device);
        URL controlUrl = service.getControlURL();

        String soapAction = service.getServiceType() + "#Pause";
        String body = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                + "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
                + "<s:Body>"
                + "<u:Pause xmlns:u=\"" + service.getServiceType() + "\">"
                + "<InstanceID>0</InstanceID>"
                + "</u:Pause>"
                + "</s:Body>"
                + "</s:Envelope>";

        sendPostRequest(controlUrl, soapAction, body);
    }

    public static void stop(Device device) throws IOException {
        Service service = getService(device);
        URL controlUrl = service.getControlURL();

        String soapAction = service.getServiceType() + "#Stop";
        String body = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                + "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
                + "<s:Body>"
                + "<u:Stop xmlns:u=\"" + service.getServiceType() + "\">"
                + "<InstanceID>0</InstanceID>"
                + "</u:Stop>"
                + "</s:Body>"
                + "</s:Envelope>";

        sendPostRequest(controlUrl, soapAction, body);
    }

    // TODO: Implement seek, getPositionInfo, setVolume, getVolume, etc.

    private static String sendPostRequest(URL url, String soapAction, String body) throws IOException {
        HttpURLConnection connection = null;
        try {
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "text/xml; charset=\"utf-8\"");
            connection.setRequestProperty("SOAPACTION", "\"" + soapAction + "\"");
            connection.setFixedLengthStreamingMode(body.getBytes().length);

            connection.getOutputStream().write(body.getBytes());

            int responseCode = connection.getResponseCode();
            if (responseCode == HTTP_OK) {
                return HttpUtil.readStream(connection.getInputStream());
            } else {
                String error = HttpUtil.readStream(connection.getErrorStream());
                throw new IOException("HTTP POST request failed with response code: " + responseCode + ", Error: " + error);
            }
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}